package group.rober.jeki.service;

import group.rober.common.CommonConsts;
import group.rober.common.service.FileManageService;
import group.rober.jeki.entity.Article;
import group.rober.jeki.entity.Tag;
import group.rober.jeki.exception.JekiException;
import group.rober.runtime.kit.DateKit;
import group.rober.runtime.kit.MapKit;
import group.rober.runtime.kit.NumberKit;
import group.rober.runtime.kit.StringKit;
import group.rober.runtime.lang.MapData;
import group.rober.search.entity.SearchResult;
import group.rober.search.service.SearchService;
import group.rober.sql.core.DataAccessor;
import group.rober.sql.core.MapDataAccessor;
import group.rober.runtime.model.PaginationData;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Service
public class ArticleService {
    private String defaultSortClause = " STICK desc,SCORE desc,VIEW_COUNT desc,COMMENT_COUNT desc,GOOD_COUNT desc,BAD_COUNT asc ,ID desc";

    @Autowired
    private DataAccessor dataAccessor;
    @Autowired
    private MapDataAccessor mapDataAccessor;
    @Autowired
    TagService tagService;
    @Autowired
    @Qualifier(CommonConsts.DOC_FILE_SERVICE_NAME)
    FileManageService docFileService;
    @Autowired
    SearchService searchService;


    public Article getArticle(String id){
        return dataAccessor.selectOne(Article.class,"select * from JEKI_ARTICLE where ID=:id", MapKit.mapOf("id",id));
    }
    public void incrementViewCount(String id){
        String sql = "update JEKI_ARTICLE set VIEW_COUNT=VIEW_COUNT+1 where ID=:id";
        dataAccessor.execute(sql, MapKit.mapOf("id",id));
    }

    public void saveArticle(Article article){
        //保存文章
        dataAccessor.save(article);
        //保存并处理标签
        String tags = article.getTags();
        if(StringKit.isNotBlank(tags)){
            String[] tagsArray = tags.split(",");
            saveTags(tagsArray,article.getId());
        }
    }

    protected void saveTags(String[] tags,String articleId){
        for(String tagName : tags){
            //标签不存在，则创建它
            Tag tag = tagService.getTagByName(tagName);
            if(tag==null){
                tag = new Tag();
                tag.setId(NumberKit.nanoTime36());
                tag.setName(tagName);
                tag.setCode(tagName);
                tag.setReferCount(0);
            }
            tag.setReferCount(tag.getReferCount()+1);
            tagService.saveTag(tag);

            //建立标签和文章的关联
            Map<String,?> paraMap = MapKit.mapOf("articleId", articleId, "tagId", tag.getId());
            MapData articleTag = mapDataAccessor.selectOne("select * from JEKI_ARTICLE_TAG where ARTICLE_ID=:articleId and TAG_ID=:tagId"
                    ,paraMap);
            if(articleTag==null){
                articleTag = new MapData();
                articleTag.put("id", NumberKit.nanoTime36());
                articleTag.put("articleId",articleId);
                articleTag.put("tagId",tag.getId());
                mapDataAccessor.insert("JEKI_ARTICLE_TAG",articleTag);
            }else{
                MapData keyAttrs = new MapData();
                keyAttrs.put("id",articleTag.getValue("id").strValue());
                mapDataAccessor.update("JEKI_ARTICLE_TAG",articleTag,keyAttrs);
            }
        }
    }

    public void deleteArticle(String id){
        docFileService.delete(id);
        mapDataAccessor.execute("delete from JEKI_ARTICLE where ID=:id", MapKit.mapOf("id",id));
    }

    public void stickArticle(String articleId){
        String sql = "update JEKI_ARTICLE set STICK=:stick where ID=:articleId";
        Map<String,Object> vars = MapKit.newHashMap();
        vars.put("articleId",articleId);
        vars.put("stick", DateKit.now().getTime()/1000+3600*24*7);//置顶时间为7天,最小单位为秒
        dataAccessor.execute(sql,vars);
    }
    public void cancelArticle(String articleId){
        String sql = "update JEKI_ARTICLE set STICK=:stick where ID=:articleId";
        Map<String,Object> vars = MapKit.newHashMap();
        vars.put("articleId",articleId);
        vars.put("stick", 0);//置顶时间为7天,最小单位为秒
        dataAccessor.execute(sql,vars);
    }

    public List<Article> getStickedArticleList(){
        String sql = "select * from JEKI_ARTICLE where STICK>0 order by "+defaultSortClause;
        return dataAccessor.selectList(Article.class,sql);
    }

    public List<Article> getRecentArticleList(int pageIndex,int pageSize){
        String sql = "select * from JEKI_ARTICLE where 1=1 order by CREATED_TIME desc ,"+defaultSortClause;
        Map<String,?> paramMap = MapKit.newHashMap();
        PaginationData<Article> result = dataAccessor.selectListPagination(Article.class,sql,paramMap,pageIndex,pageSize);
        return result.getDataList();
    }

    public List<Article> getAllArticleList(){
        String sql = "select * from JEKI_ARTICLE where 1=1 order by "+defaultSortClause;
        return dataAccessor.selectList(Article.class,sql);
    }

    public PaginationData<Article> getArticleList(int pageIndex,int pageSize){
        String sql = "select * from JEKI_ARTICLE where 1=1 order by "+defaultSortClause;
        Map<String,?> paramMap = MapKit.newHashMap();
        PaginationData<Article> result = dataAccessor.selectListPagination(Article.class,sql,paramMap,pageIndex,pageSize);
        return result;
    }

    public PaginationData<Article> getArticleListByDomain(String domainCode, int pageIndex, int pageSize){
        StringBuffer sqlBuffer = new StringBuffer();
        sqlBuffer.append(" select * from JEKI_ARTICLE A");
        sqlBuffer.append(" WHERE EXISTS(");
        sqlBuffer.append(" SELECT 1 FROM ");
        sqlBuffer.append("     JEKI_ARTICLE_TAG R, ");
        sqlBuffer.append("     JEKI_DOMAIN_TAG R1, ");
        sqlBuffer.append("     JEKI_DOMAIN D ");
        sqlBuffer.append(" WHERE");
        sqlBuffer.append("     R.ARTICLE_ID = A.ID");
        sqlBuffer.append("     AND R.TAG_ID = R1.TAG_ID");
        sqlBuffer.append("     AND R1.DOMAIN_ID = D.ID");
        sqlBuffer.append("     AND D.CODE = :domainCode");
        sqlBuffer.append(" )");
        sqlBuffer.append(" order by ");
        sqlBuffer.append(defaultSortClause);

        String sql = sqlBuffer.toString();
        Map<String,?> paramMap = MapKit.mapOf("domainCode",domainCode);
        return dataAccessor.selectListPagination(Article.class,sql,paramMap,pageIndex,pageSize);

    }

    public PaginationData<Article> getArticleListByTag(String tagCode, int pageIndex, int pageSize){
        StringBuffer sqlBuffer = new StringBuffer();
        sqlBuffer.append(" select * from JEKI_ARTICLE A");
        sqlBuffer.append(" WHERE EXISTS(");
        sqlBuffer.append(" SELECT 1 FROM ");
        sqlBuffer.append("     JEKI_ARTICLE_TAG R,");
        sqlBuffer.append("     JEKI_TAG T");
        sqlBuffer.append(" WHERE");
        sqlBuffer.append("     R.ARTICLE_ID = A.ID");
        sqlBuffer.append("     AND R.TAG_ID = T.ID");
        sqlBuffer.append("     AND T.CODE = :tagCode");
        sqlBuffer.append(" )");
        sqlBuffer.append(" order by ");
        sqlBuffer.append(defaultSortClause);

        Map<String,?> paramMap = MapKit.mapOf("tagCode",tagCode);
        String sql = sqlBuffer.toString();
        return dataAccessor.selectListPagination(Article.class,sql,paramMap,pageIndex,pageSize);
    }

    public SearchResult searchArticles(String keyWords,int index,int size){
        SearchResult result = null;
        Sort sort=new Sort(new SortField[]{new SortField("viewCount",SortField.Type.STRING),new SortField("updatedTime",SortField.Type.STRING)});

        try {
            result = searchService.searchDocument(new String[]{"title","summary","content"},keyWords,sort,index,size);
        } catch (ParseException e) {
            throw new JekiException("搜索出错，搜索表达式解析出错",e);
        } catch (IOException e) {
            throw new JekiException("搜索出错，索引文件读写出错",e);
        }
        return result;
    }

    /**
     * 重新计算处理标签的引用值
     */
    public void statisticsArticleTag(){
        dataAccessor.update("update JEKI_TAG set REFER_COUNT=0 where REFER_COUNT>0");
        List<Article> articles = dataAccessor.selectList(Article.class,"select * from JEKI_ARTICLE");
        for(Article article : articles){
            String tags = article.getTags();
            if(StringKit.isNotBlank(tags)){
                String[] tagsArray = tags.split(",");
                saveTags(tagsArray,article.getId());
            }
        }
        dataAccessor.delete("delete from JEKI_TAG where CODE=NAME and REFER_COUNT=0");//引用为0且没指定标签代码的删除掉
        dataAccessor.delete("delete from JEKI_ARTICLE_TAG where ARTICLE_ID not in(select ID from JEKI_ARTICLE)");//引用表中文章不存在的
        dataAccessor.delete("delete from JEKI_ARTICLE_TAG where TAG_ID not in(select ID from JEKI_TAG)");       //引用表中标签不存在的
        dataAccessor.delete("delete from JEKI_DOMAIN_TAG where TAG_ID not in(select ID from JEKI_TAG)");       //领域关联表中标签不存在的
    }

}
